package messages

import (
	
	

	
	
	
	
	
	
	
	
	
)

// KRBPriv implements RFC 4120 type: https://tools.ietf.org/html/rfc4120#section-5.7.1.
type KRBPriv struct {
	PVNO             int                 `asn1:"explicit,tag:0"`
	MsgType          int                 `asn1:"explicit,tag:1"`
	EncPart          types.EncryptedData `asn1:"explicit,tag:3"`
	DecryptedEncPart EncKrbPrivPart      `asn1:"optional,omitempty"` // Not part of ASN1 bytes so marked as optional so unmarshalling works
}

// EncKrbPrivPart is the encrypted part of KRB_PRIV.
type EncKrbPrivPart struct {
	UserData       []byte            `asn1:"explicit,tag:0"`
	Timestamp      time.Time         `asn1:"generalized,optional,explicit,tag:1"`
	Usec           int               `asn1:"optional,explicit,tag:2"`
	SequenceNumber int64             `asn1:"optional,explicit,tag:3"`
	SAddress       types.HostAddress `asn1:"explicit,tag:4"`
	RAddress       types.HostAddress `asn1:"optional,explicit,tag:5"`
}

// NewKRBPriv returns a new KRBPriv type.
func ( EncKrbPrivPart) KRBPriv {
	return KRBPriv{
		PVNO:             iana.PVNO,
		MsgType:          msgtype.KRB_PRIV,
		DecryptedEncPart: ,
	}
}

// Unmarshal bytes b into the KRBPriv struct.
func ( *KRBPriv) ( []byte) error {
	,  := asn1.UnmarshalWithParams(, , fmt.Sprintf("application,explicit,tag:%v", asnAppTag.KRBPriv))
	if  != nil {
		return processUnmarshalReplyError(, )
	}
	 := msgtype.KRB_PRIV
	if .MsgType !=  {
		return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a KRB_PRIV. Expected: %v; Actual: %v", , .MsgType)
	}
	return nil
}

// Unmarshal bytes b into the EncKrbPrivPart struct.
func ( *EncKrbPrivPart) ( []byte) error {
	,  := asn1.UnmarshalWithParams(, , fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncKrbPrivPart))
	if  != nil {
		return krberror.Errorf(, krberror.EncodingError, "KRB_PRIV unmarshal error")
	}
	return nil
}

// Marshal the KRBPriv.
func ( *KRBPriv) () ([]byte, error) {
	 := KRBPriv{
		PVNO:    .PVNO,
		MsgType: .MsgType,
		EncPart: .EncPart,
	}
	,  := asn1.Marshal()
	if  != nil {
		return []byte{}, 
	}
	 = asn1tools.AddASNAppTag(, asnAppTag.KRBPriv)
	return , nil
}

// EncryptEncPart encrypts the DecryptedEncPart within the KRBPriv.
// Use to prepare for marshaling.
func ( *KRBPriv) ( types.EncryptionKey) error {
	,  := asn1.Marshal(.DecryptedEncPart)
	if  != nil {
		return 
	}
	 = asn1tools.AddASNAppTag(, asnAppTag.EncKrbPrivPart)
	.EncPart,  = crypto.GetEncryptedData(, , keyusage.KRB_PRIV_ENCPART, 1)
	if  != nil {
		return 
	}
	return nil
}

// DecryptEncPart decrypts the encrypted part of the KRBPriv message.
func ( *KRBPriv) ( types.EncryptionKey) error {
	,  := crypto.DecryptEncPart(.EncPart, , keyusage.KRB_PRIV_ENCPART)
	if  != nil {
		return fmt.Errorf("error decrypting KRBPriv EncPart: %v", )
	}
	 = .DecryptedEncPart.Unmarshal()
	if  != nil {
		return fmt.Errorf("error unmarshaling encrypted part: %v", )
	}
	return nil
}